﻿using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Tyshka.Subroutines.Domain.Abstract;
using Tyshka.Subroutines.Domain.Entities;
using Tyshka.Subroutines.Kernel;

namespace Tyshka.Subroutines.Domain.Infrastructure.Auth
{
    public static class LoginUtils
    {
        private static IUserRepository userRepository
        {
            get { return (IUserRepository)DependencyResolver.Current.GetService(typeof(IUserRepository)); }
        }

        public static ISecurityContext SecurityContext
        {
            get { return (ISecurityContext)LoginUtils.AuthenticateRequest(); }
        }

        public static User CurrentUser
        {
            get
            {
                if (SecurityContext != null)
                {
                    return SecurityContext.User;
                }
                return null;
            }
        }

        public static ISecurityContext AuthenticateRequest()
        {
            FormsAuthenticationTicket ticket = null;
            HttpCookie cookie = GetAuthenticationCookie(HttpContext.Current.Request);

            if (cookie != null && !String.IsNullOrEmpty(cookie.Value))
            {
                try
                {
                    ticket = FormsAuthentication.Decrypt(cookie.Value);
                }
                catch (Exception)
                {
                    // Supress all exceptions.
                    // TODO: Log this case
                }
            }

            if (ticket != null)
            {
                var account = userRepository.ReadByCredentials(ticket.Name, ticket.UserData);

                if (account != null)
                {
                    if (cookie.Name.Equals(Constants.Login.RememberMeCookieName))
                    {
                        SignIn(account);
                    }

                    account.IsLogged = true;
                    return new SecurityContext(account, PermissionTypes.User);
                }
            }

            return new SecurityContext(new User { IsLogged = false }, PermissionTypes.Guest);
        }

        /// <summary>
        /// Creates encrypted authentication cookie
        /// </summary>
        /// <param name="account">Account to put in cookie</param>
        public static void SignIn(User account)
        {
            SignIn(account, false);
        }

        /// <summary>
        /// Creates encrypted authentication cookie
        /// </summary>
        /// <param name="account">Account to put in cookie</param>
        /// <param name="remember">If true then user credentials will be remembered.</param>
        public static void SignIn(User account, bool remember)
        {
            var ticket = new FormsAuthenticationTicket
                (1,
                 account.Login,
                 DateTime.Now,
                 DateTime.Now.AddDays(Constants.Login.AuthenticationExpiryDays),
                 true,
                 account.Password,
                 FormsAuthentication.FormsCookiePath);

            String encryptedTicket = FormsAuthentication.Encrypt(ticket);

            // add the forms authentication cookie to the response
            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            cookie.Path = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath);
            HttpContext.Current.Response.Cookies.Add(cookie);

            // set separate cookie in case if system should remember this user
            if (remember)
            {
                AddRememberMeCookie(encryptedTicket);
            }

            //StatisticsLogger.Info(LogType.LoginAndLogout, account.Login, String.Format("User {0} has logged in.", account.Login));
        }

        public static void SignOut(HttpContextBase context)
        {
            //StatisticsLogger.Info(LogType.LoginAndLogout, CurrentUserAccount.Login, String.Format("User {0} has logged out.", CurrentUserAccount.Login));
            context.Session.Clear();
            HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, String.Empty);
            cookie.Expires = DateTime.Now;
            cookie.Path = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath);
            HttpContext.Current.Response.Cookies.Add(cookie);

            RemoveRememberMeCookie();
        }

        public static void AddRememberMeCookie(String encryptedTicket)
        {
            var cookie = new HttpCookie(Constants.Login.RememberMeCookieName, encryptedTicket);
            cookie.Expires = DateTime.Now.AddDays(Constants.Login.RememberMeCookieExpiryDays);
            cookie.Path = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath);

            HttpContext.Current.Response.Cookies.Add(cookie);
        }

        public static void RemoveRememberMeCookie()
        {
            HttpContext.Current.Response.Cookies.Remove(Constants.Login.RememberMeCookieName);
            var cookie = new HttpCookie(Constants.Login.RememberMeCookieName, String.Empty);
            cookie.Expires = DateTime.Now;
            cookie.Path = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath);
            HttpContext.Current.Response.Cookies.Add(cookie);
        }

        private static HttpCookie GetAuthenticationCookie(HttpRequest request)
        {
            var cookie = request.Cookies[FormsAuthentication.FormsCookieName];
            if (cookie == null)
            {
                cookie = request.Cookies[Constants.Login.RememberMeCookieName];
            }
            return cookie;
        }



    }
}
